package com.ztesoft.web.cleanup.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.ztesoft.core.threadpool.GeneralThreadPool;
import com.ztesoft.core.threadpool.ThreadPoolFactory;
import com.ztesoft.framework.exception.BaseAppException;
import com.ztesoft.framework.log.ZTEsoftLogManager;
import com.ztesoft.framework.util.DateUtils;
import com.ztesoft.framework.util.Utils;
import com.ztesoft.web.baseconfig.db.arg.DmTargetTableArg;
import com.ztesoft.web.baseconfig.db.dao.DmTargetTableDao;
import com.ztesoft.web.baseconfig.db.po.DmPlanPO;
import com.ztesoft.web.baseconfig.db.po.DmSrcTablePO;
import com.ztesoft.web.baseconfig.db.po.DmStrategyPO;
import com.ztesoft.web.baseconfig.db.po.DmTargetTablePO;
import com.ztesoft.web.cleanup.CleanUpTask;
import com.ztesoft.web.cleanup.service.CleanUpService;
import com.ztesoft.web.common.DMSConstant;
import com.ztesoft.web.common.Util;
import com.ztesoft.web.common.customdb.dao.DmPlanCustomDao;
import com.ztesoft.web.common.customdb.dao.DmSrcTableCustomDao;
import com.ztesoft.web.common.customdb.dao.DmStrategyCustomDao;
import com.ztesoft.web.common.customdb.dao.DmTaskStageCustomDao;
import com.ztesoft.web.common.customdb.dao.dto.DmTaskStageDto;
import com.ztesoft.web.common.db.dao.DmDao;
import com.ztesoft.web.common.db.dao.DmSecondaryStageDao;
import com.ztesoft.web.filecommon.db.arg.DmFArg;
import com.ztesoft.web.filecommon.db.dao.DmFDao;
import com.ztesoft.web.filecommon.db.po.DmFPO;
import com.ztesoft.web.syncbaseinfo.service.BaseInfoService;
import com.ztesoft.web.taskgenerator.db.dao.DmTaskDao;
import com.ztesoft.web.taskgenerator.db.dao.DmTaskStageDao;


/**
 * 
 *  
 * @author lin.weibin@zte.com.cn
 * @date 2015年12月25日
 * @since 1.0
 */
@Service
public class CleanUpServiceImpl implements CleanUpService{
	
	/**
	 * 日志
	 */
    private static final ZTEsoftLogManager LOGGER = ZTEsoftLogManager
            .getLogger(CleanUpServiceImpl.class);

	@Autowired
	private DmPlanCustomDao planCustomDao;
	
	@Autowired
	private DmSrcTableCustomDao srcTableCustomDao;
	
	@Autowired
	private DmStrategyCustomDao strategyCustomDao;
	
	@Autowired
	private DmTaskStageCustomDao taskStageCustomDao;
	
	@Autowired
	private DmTaskDao dmTaskDao;
	
	@Autowired
	private DmDao dmDao;
	
	@Autowired
	private BaseInfoService baseInfoService;
	
	@Autowired
	private DmSecondaryStageDao dmSecondaryStageDao;
	
	@Autowired
	private DmTargetTableDao targetTableDao;
	
	@Autowired
	private DmTaskStageDao dmTaskStageDao;
	
	@Autowired
	private DmFDao dmFDao;
	/**
	 * 供任务调度调用
	 * @param taskId
	 * @param strategyId
	 * @return
	 * @throws BaseAppException
	 */
	@Override
	public String cleanUp(int taskId, int strategyId) throws BaseAppException{
		return doCleanUp(taskId, strategyId, null);
	}
	
	/**
	 * 供备份失败调用  	modified by wb.l 2015.12.15 备份失败不做清理处理，改备份取消调用做清理目标操作
	 * @param taskId
	 * @param strategyId
	 * @param stage
	 * @return
	 * @throws BaseAppException
	 */
	@Override
	public String cleanUp(int taskId, int strategyId, Integer stage) throws BaseAppException{
		return doCleanUp(taskId, strategyId, stage);
	}
	
	private String doCleanUp(int taskId, int strategyId, Integer stage) throws BaseAppException{
		LOGGER.info(Thread.currentThread()+(stage == null? "任务调度": "备份取消调用")+"|++===清理服务|任务ID={0},策略ID={1}BEGIN..",taskId,strategyId);
		String checkState = DMSConstant.Status.SUCCESS.getState();
		String state = "00T";
		if(stage != null && stage == 4){
			state = "00F";
		}
		List<DmTaskStageDto> taskStageList = taskStageCustomDao.selectTaskStageList(taskId, strategyId, DMSConstant.STAGE_CLEANUP, state);
		if (Utils.isEmpty(taskStageList)) {
			LOGGER.info(Thread.currentThread()+"|查询待清理任务环节列表|"+taskStageList);
			return DMSConstant.Status.SUCCESS.getState();//
		}
		List<Future<DmTaskStageDto>> futureList = new ArrayList<Future<DmTaskStageDto>>(taskStageList.size());
		LOGGER.debug("|根据策略ID取seq值最大一条数据|strategyId="+strategyId);
		DmStrategyPO stgPO = strategyCustomDao.selectTopSeqPOById(strategyId);
		LOGGER.debug("|查询计划实例|taskId="+taskId);
		DmPlanPO planPO = planCustomDao.selectByTaskId(taskId);
		int oneRecordSize = 1;
		//创建连接池
		GeneralThreadPool ctp = null;
		
		//
		if ((int)planPO.getSourceType() == DMSConstant.SOURCE_TYPE_FILE) { //文件
			ctp = ThreadPoolFactory.createGeneralBoundedThreadPool("clean up {taskId="+taskId+",strategyId="+strategyId+"}...", //
					stgPO.getConcurrentNumber(), stgPO.getConcurrentNumber());
			for (DmTaskStageDto taskStagePO : taskStageList) {
				LOGGER.info("1、更新环节记录--");
				taskStagePO.setState("00R");
				taskStagePO.setStateDate(new Date());
				taskStagePO.setTaskStartTime((taskStagePO.getTaskStartTime()!=null)?null:new Date());
				taskStagePO.setTaskEndTime(null);
				taskStageCustomDao.updateTaskStageState(taskStagePO);
				
				//获取文件脚本操作轨迹表记录
				DmFArg arg = new DmFArg();
				DmFArg.DmFCriteria criteria = arg.createCriteria();
				criteria.andDmTaskIdEqualTo(taskStagePO.getDmTaskId());
				criteria.andDmInfoIdEqualTo((int)planPO.getOperType() == 0 ? (taskStagePO.getDmInfoId() - 2):(taskStagePO.getDmInfoId() - 1));//体检infoid
				List<String> stateArgList = new ArrayList<String>();
				stateArgList.add("00T");
				stateArgList.add("00R");
				criteria.andStateIn(stateArgList);
				arg.setOrderByClause("src_ip");
				arg.setTableName("dm_f_"+taskStagePO.getDmStrategyId());
				List<DmFPO> dmFPOList = dmFDao.selectByArg(arg);
				LOGGER.info("2、获取文件脚本操作轨迹表记录{0}--",dmFPOList.size());
				if (Utils.isEmpty(dmFPOList)) {
					checkState = DMSConstant.Status.SUCCESS.getState();
					taskStagePO.setState(checkState);
					taskStagePO.setStateDate(new Date());
					taskStagePO.setTaskStartTime((taskStagePO.getTaskStartTime()!=null)?null:new Date());
					taskStagePO.setTaskEndTime(null);
					taskStageCustomDao.updateTaskStageState(taskStagePO);
					continue;
				}
				
				Future<DmTaskStageDto> future = ctp.submit(new CleanUpFileTask(taskStagePO, dmFPOList, planPO));
				futureList.add(future);
			}
		} else { //表
			LOGGER.debug("|根据策略标识查询出执行源主对象信息|strategyId="+strategyId);
			DmSrcTablePO srcTablePO = srcTableCustomDao.selectByStrategyId(strategyId);
			oneRecordSize = srcTablePO.getOneRecordSize();
			/*
			 * 数据库链接~  modified by lin.weibin 2015.12.15
			 */
			String[] dbConfig = null;
			if (stage == null) {//
				dbConfig = baseInfoService.getDbConfig(srcTablePO.getDbLinkId(), srcTablePO.getDbUserName());
			} else {
				LOGGER.debug("获取目标表数据库配置---");
				DmTargetTableArg dmTargetTableArg = new DmTargetTableArg();
				DmTargetTableArg.DmTargetTableCriteria targetTableCriteria = dmTargetTableArg.createCriteria();
				targetTableCriteria.andSourceDataIdEqualTo(srcTablePO.getSourceDataId());
				DmTargetTablePO targetPO = targetTableDao.selectByArg(dmTargetTableArg).get(0);
				dbConfig = baseInfoService.getDbConfig(targetPO.getDbLinkId(), targetPO.getDbUserName());
			}
			LOGGER.debug("|策略{0}|数据库信息："+(dbConfig[0]+","+dbConfig[1]+","+dbConfig[2]+","+dbConfig[3]), strategyId);
			//线程处理
			ctp = ThreadPoolFactory.createGeneralBoundedThreadPool("clean up {taskId="+taskId+",strategyId="+strategyId+"}...", //
					stgPO.getConcurrentNumber() >= taskStageList.size() ? taskStageList.size() : stgPO.getConcurrentNumber(),// 
					taskStageList.size());
			for (DmTaskStageDto taskStagePO : taskStageList) {
				Future<DmTaskStageDto> future = ctp.submit(new CleanUpTask(taskStagePO, planPO, srcTablePO, dbConfig, stgPO, stage));
				futureList.add(future);
			}
		}
		int sucessInt = 0,failInt = 0,stopInt = 0, sysStopInt = 0, cancelInt = 0;//
		//如果线程都空闲且无待处理的任务环节记录，则先将所有00A状态的任务明细记录移至历史表并删除任务明细记录，然后返回成功，流程结束
		for (Future<DmTaskStageDto> future : futureList) {
			try {
				LOGGER.info("|清理："+future.get().getCheckObjName()+"表END|:::"+future.get().getCheckState());
				
				if ("success".equals(future.get().getCheckState())) {
					sucessInt = sucessInt + 1;
				} else if ("fail".equals(future.get().getCheckState())){
					failInt = failInt + 1;
				} else if ("00C".equals(future.get().getCheckState())) {
					cancelInt = cancelInt + 1;
				} else if ("00P".equals(future.get().getCheckState())) {
					stopInt = stopInt + 1;
				} else if ("02P".equals(future.get().getCheckState())) {
					sysStopInt = sysStopInt + 1;
				}
				
				if ("success".equals(future.get().getCheckState())|| "fail".equals(future.get().getCheckState())) {//处理结果数据、更新环节、从表
					future.get().setTaskStartTime(null);//避免数据插入
					future.get().setTaskEndTime(DateUtils.getDBCurrentTime());
					future.get().setStateDate(DateUtils.getDBCurrentTime());
					if (future.get().getDataType() == 1) {						
						future.get().setCheckDataSize(Util.divValue2BigDecimal(oneRecordSize, future.get().getCheckCount(), 2));
						dmSecondaryStageDao.updateSecondaryStageState(DateUtils.getDBCurrentTime(), future.get().getState(), future.get().getDmInfoId());
					}
					taskStageCustomDao.updateTaskStageState(future.get());
				}
			} catch (InterruptedException e) {
				e.printStackTrace();
			} catch (ExecutionException e) {
				e.printStackTrace();
			}
		}
		
		LOGGER.info("|++===清理服务|任务ID={0},策略ID={1}END...",taskId,strategyId);
		LOGGER.info("{0}|++===清理服务|任务END..sucessInt:"+sucessInt+",failInt:"+failInt+",stopInt:"+stopInt+"sysStopInt:"+sysStopInt+"cancelInt,:"+cancelInt,Thread.currentThread());
		if (cancelInt > 0){
			checkState = "00C";//取消
		} else if (sysStopInt > 0) {
			checkState = "02P";//系统暂停
		} else if (stopInt > 0) {
			checkState = "00P";//暂停
		} else if (failInt > 0/*== futureList.size()*/) {
			checkState = "00F";//失败
		} else {					
			checkState = "00A";//成功
		}
		ctp.shutDown();
		return checkState;
	}


}
